﻿using System.Runtime.CompilerServices;
using Microsoft.AspNetCore.Mvc;

namespace ChatGpt_WebApp
{
    public static class TokenManager
    {
        public static List<TokenState> TokenStates { get; private set; } = new List<TokenState>();

        public static event Action<TokenState>? OnTokenExpired;

        public static void LoadToken()
        {
            TokenStates.ForEach(f => f.OnExpired -= S_OnExpired);
            TokenStates = AppSetting.Current.ChatGpt.TokenPool.Select(s => new TokenState(s)).ToList();
            TokenStates.ForEach(s =>
            {
                s.OnExpired += S_OnExpired;
            });
        }

        private static void S_OnExpired(object? sender, EventArgs e)
        {
            OnTokenExpired?.Invoke((sender as TokenState)!);
        }

        /// <summary>
        /// 根据Id获取一个Token
        /// </summary>
        /// <param name="tokenId"></param>
        /// <returns></returns>
        public static TokenState? GetToken(int tokenId)
        {
            return TokenStates.FirstOrDefault(f => f.TokenId == tokenId);
        }

        /// <summary>
        /// 随机获取一个可用的Token
        /// </summary>
        /// <returns></returns>
        public static TokenState? RandomOne()
        {
            var noExpired = TokenStates.Where(w => w.Expired == false).ToArray();
            if (noExpired.Length == 0) return null;
            if (noExpired.Length == 1) return noExpired[0];

            return noExpired[new Random().Next(noExpired.Length)];            
        }

        /// <summary>
        /// 更新Token
        /// </summary>
        /// <param name="tokenId"></param>
        public static void UpdateToken(int tokenId,string newTokenValue)
        {
            var token = GetToken(tokenId);
            if (token == null) throw new BusinessException("无效的TokenID");            
        }
    }

    public class TokenState
    {
        private TokenItem info;

        public event EventHandler? OnExpired;

        public int TokenId { get => info.Id; }

        public string TokenValue { get => info.SessionToken; }

        private bool _expired = false;

        /// <summary>
        /// Token是否已过期
        /// </summary>
        public bool Expired
        {
            get
            {
                return _expired;
            }
            set
            {
                if (_expired == value) return;
                _expired = value;
                if (!_expired)
                {
                    OnExpired?.Invoke(this, EventArgs.Empty);
                }
            }
        }

        /// <summary>
        /// 是否已被频率过高限制
        /// </summary>
        public bool Confined { get; set; }

        public TokenState(TokenItem tokenInfo)
        {
            this.info = tokenInfo;
        }
    }
}
